package net.csdra.basis.service;

import net.csdra.basis.Utils;
import net.csdra.basis.domain.CJpaRepository;
import net.csdra.basis.domain.EntityBase;
import net.csdra.basis.domain.UserBaseInterface;
import net.csdra.user.domain.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.sql.Timestamp;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Created by msf on 2018/1/26.
 * 此实现类为借口ServiceBaseInterface提供一个默认实现，实现ServiceBaseInterface接口可继承自此类，此类部分方法不负责持久化（请注意看注释）
 */
public class ServiceBaseInterfaceImpl<T extends EntityBase, C extends ServiceBaseInterface.Create, U extends ServiceBaseInterface.Update> implements ServiceBaseInterface<T, C, U> {

    private Class<T> t;
    CJpaRepository<T, String> jpaRepository;
    CurrentUserInfo currentUserInfo;

    public ServiceBaseInterfaceImpl(Class<T> t, CJpaRepository<T, String> jpaRepository, CurrentUserInfo currentUserInfo) {
        this.t = t;
        this.jpaRepository = jpaRepository;
        this.currentUserInfo = currentUserInfo;
    }

    /**
     * 创建一个新的实体，此方法不负责持久化
     *
     * @param c
     * @return
     */
    @Override
    public T create(C c) {
        Assert.notNull(c, "参数不能为空");
        Assert.notNull(c.getCustomize(), "customize值不能为空");
        Assert.hasLength(c.getMetaId(), "metaId值不能为空");
        try {
            T t = this.t.newInstance();
            Utils.copyProperties(c, t);
            t.setMetaId(c.getMetaId());
            t.setCustomize(c.getCustomize());
            t.setId(UUID.randomUUID().toString());
            UserBaseInterface userBaseInterface = currentUserInfo.get();
            t.setCreateBy(userBaseInterface.getUserName());
            t.setLastModifiedBy(userBaseInterface.getUserName());
            t.setDeleted(false);
            t.setEnabled(false);
            t.setLastModifiedTime(new Timestamp(new Date().getTime()));
            t.setCreateTime(new Timestamp(new Date().getTime()));
            t.setOrder(0L);
            this.jpaRepository.save(t);
            T result = this.t.newInstance();
            Utils.copyProperties(t, result);
            return result;

        } catch (Exception e) {
            throw new RuntimeException("创建对象失败", e);
        }
    }

    /**
     * 根据ID修改一个实体，此方法不负责持久化
     *
     * @param u
     * @return
     */
    @Override
    public T update(U u) {
        Assert.notNull(u, "参数不能为空");
        Assert.hasLength(u.getId(), "操作对象Id不能为空");
        T one = jpaRepository.findOne(u.getId());
        Assert.notNull(one, "修改对象不存在");
        UserBaseInterface userBaseInterface = currentUserInfo.get();
        Utils.copy(u, one);
        one.setLastModifiedTime(new Timestamp(new Date().getTime()));
        one.setLastModifiedBy(userBaseInterface.getUserName());
        this.jpaRepository.save(one);
        T result = null;
        try {
            result = this.t.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        Utils.copyProperties(t, result);
        return result;
    }

    /**
     * 根据id将实体标记为删除，已持久化
     *
     * @param id
     */
    @Override
    public void deleteCurrent(String id) {
        Assert.hasLength(id, "id不能为空");
        T one = jpaRepository.findOne(id);
        Assert.notNull(one, "删除对象不存在");
        one.setDeleted(true);
        jpaRepository.save(one);

    }

    @Override
    public T enabledCurrent(String id, boolean isEnabled) {
        Assert.hasLength(id, "id不能为空");
        T one = jpaRepository.findOne(id);
        Assert.notNull(one, "删除对象不存在");
        one.setEnabled(isEnabled);
        jpaRepository.save(one);
        T t = null;
        try {
            t = this.t.newInstance();
        } catch (Exception e) {
            throw new RuntimeException("创建返回对象时失败", e);
        }
        Utils.copyProperties(one, t);
        return t;
    }

    @Override
    public T findOne(String id) {
        Assert.hasLength(id, "id不能为空");
        return jpaRepository.findOne(id);
    }

    @Override
    public T findOneAndEnabledIsTrue(String id) {
        Assert.hasLength(id, "id不能为空");
        return jpaRepository.findByIdAndEnabledIsTrue(id);
    }

    @Override
    public List<T> findAllByMetaId(String metaId) {
        Assert.hasLength(metaId, "metaId不能为空");
        return jpaRepository.findByMetaId(metaId);
    }

    @Override
    public List<T> findAllByMetaId(String metaId, boolean isEnabled) {
        Assert.hasLength(metaId, "metaId不能为空");
        return jpaRepository.findByMetaIdAndEnabledIsTrue(metaId);
    }

    @Override
    public Page<T> findPageByMetaId(String metaId, Pageable pageable) {
        Assert.hasLength(metaId, "metaId不能为空");
        Assert.notNull(pageable, "pageable不能为空");
        return jpaRepository.findByMetaId(metaId, pageable);
    }

    @Override
    public Page<T> findPageByMetaId(String metaId, boolean isEnabled, Pageable pageable) {
        Assert.hasLength(metaId, "metaId不能为空");
        Assert.notNull(pageable, "pageable不能为空");
        return jpaRepository.findByMetaIdAndEnabledIsTrue(metaId, pageable);
    }
}
